﻿using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using ADV_Evaluator;
using ADV_Evaluator.Data;
using ADV_Evaluator.Command;


namespace ADV_Editor {

    /// <summary>
    /// メインフォーム
    /// </summary>
    public partial class MainForm : Form {

        /// <summary>
        /// プロジェクトデータ *.advproj のデータを集めたクラス
        /// </summary>
        private ProjectData projectData = null;
        /// <summary>
        /// 現在表示されているコマンド一覧リストボックス
        /// </summary>
        private CommandList activeCommandList = null;
        /// <summary>
        /// 変更されたシナリオファイルを確かめるためのハッシュ
        /// </summary>
        private Dictionary<string, bool> modifiedFiles = new Dictionary<string,bool>();
        /// <summary>
        /// シナリオファイル以外で何か変更されたらtrueにするフラグ
        /// </summary>
        private bool modified = false;


        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainForm() {
            // コンポーネントの初期化
            InitializeComponent();
            // 作業ディレクトリは初期状態でデスクトップにしておく
            Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            // 引数としてプロジェクトファイルの名前が渡されているときは、そのファイルを開く
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length >= 2) {
                string filename = Path.GetFullPath(args[1]);
                if (Path.GetExtension(filename).ToLower() == Const.ProjectExtension) {
                    OpenProject(filename);
                }
            }
        }


        #region タブ

        /// <summary>
        /// 選択しているタブが変化したとき
        /// </summary>
        private void tabControl_SelectedIndexChanged(object sender, EventArgs e) {
            // 編集するリストボックスを更新
            activeCommandList = GetActiveCommandList();
            // 選択している行数を表示
            if (activeCommandList != null) {
                toolStripStatusLabel_RowCount.Text = (activeCommandList.SelectedIndex + 1) + " 行目";
            }
        }
        /// <summary>
        /// タブ上の右クリックメニューが閉じた後
        /// </summary>
        private void contextMenu_Tab_Closed(object sender, ToolStripDropDownClosedEventArgs e) {
            // 登録抹消
            tabControl.ContextMenuStrip = null;
        }
        /// <summary>
        /// タブの右クリックメニューから「○○○.scn を保存する」を選択されたとき
        /// </summary>
        private void context_SaveTabFile_Click(object sender, EventArgs e) {
            // 保存するファイル名を、メニューのテキストから割り出し、保存
            string filename = context_SaveTabFile.Text.Replace(" の保存", "");
            SaveScenarioFile(filename);
        }
        /// <summary>
        /// タブの右クリックメニューから「閉じる」を選択されたとき
        /// </summary>
        private void context_CloseTab_Click(object sender, EventArgs e) {
            // タブコントロールにおけるマウスの位置を割り出す
            Point p = tabControl.PointToClient(new Point(contextMenu_Tab.Left, contextMenu_Tab.Top));
            // その位置にあるタブを削除する
            RemoveTab(p);
        }
        /// <summary>
        /// タブ上でクリックされたとき
        /// </summary>
        private void tabControl_MouseClick(object sender, MouseEventArgs e) {
            switch (e.Button) {
            case MouseButtons.Left:
                break;
            // 真ん中のボタン
            case MouseButtons.Middle:
                // マウスポインタがあるところのタブを削除する
                for (int i = 0; i < tabControl.TabCount; i++) {
                    if (tabControl.GetTabRect(i).Contains(e.Location)) {
                        RemoveTab(i);
                        break;
                    }
                }
                break;
            // 右クリック
            case MouseButtons.Right:
                // タブ上にマウスポインタがあるときだけ、コンテキストメニューを表示する
                tabControl.ContextMenuStrip = null;
                for (int i = 0; i < tabControl.TabCount; i++) {
                    if (tabControl.GetTabRect(i).Contains(e.Location)) {
                        // 最初のタブで about:blank なら出さない
                        if (i == 0 && tabControl.TabPages[0].Text == "about:blank") {
                            continue;
                        }
                        // 対象のタブのテキストを保存の欄のテキストに設定
                        string filename = tabControl.TabPages[i].Name;
                        context_SaveTabFile.Text = filename + " の保存";
                        // コンテキストメニューに登録し表示
                        tabControl.ContextMenuStrip = contextMenu_Tab;
                        tabControl.ContextMenuStrip.Show(tabControl, e.Location);
                        break;
                    }
                }
                break;
            }
        }
        /// <summary>
        /// 指定したインデックスのタブを消す
        /// </summary>
        /// <param name="index">消すタブのインデックス</param>
        private void RemoveTab(int index) {
            Debug.Assert((index >= 0 && index < tabControl.TabPages.Count));
            TabPage page = tabControl.TabPages[index];
            string filename = page.Name;
            // 編集済みのタブなら、確認メッセージを出す
            if (IsModified(filename)) {
                DialogResult result = MessageBox.Show(filename + " は変更されています。\n変更を保存しますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                switch (result) {
                case DialogResult.Yes:
                    SaveScenarioFile(filename);
                    break;
                case DialogResult.No:
                    break;
                }
            }
            // タブが１つで、そのタブを消そうとしているとき
            if (tabControl.TabCount == 1 && index == 0) {
                // 消さずにそのタブのコマンドリストを空にする
                ClearAllTabs();
            } else {
                // 編集済みチェックをはずす
                UncheckModified(tabControl.TabPages[index].Name);
                // タブを消す
                tabControl.TabPages.RemoveAt(index);
            }
        }
        /// <summary>
        /// 指定したファイル名を開いているタブを削除
        /// </summary>
        /// <param name="filename"></param>
        private void RemoveTab(string filename) {
            // 開いていなければ除外
            if(!tabControl.TabPages.ContainsKey(filename)){
                return;
            }
            RemoveTab(tabControl.TabPages.IndexOfKey(filename));
        }
        /// <summary>
        /// 指定したマウスポインタの位置にあるタブを削除する
        /// </summary>
        /// <param name="p">マウスポインタの位置</param>
        private void RemoveTab(Point p) {
            for (int i = 0; i < tabControl.TabCount; i++) {
                if (tabControl.GetTabRect(i).Contains(p)) {
                    RemoveTab(i);
                    break;
                }
            }
        }
        /// <summary>
        /// 最初のタブを残してすべてのタブを削除
        /// </summary>
        private void ClearAllTabs() {
            // 一旦全て削除し最初のを追加する
            TabPage firstTab = tabControl.TabPages[0];
            firstTab.Text = "about:blank";
            firstTab.Name = "";
            this.tabControl.TabPages.Clear();
            this.tabControl.TabPages.Add(firstTab);
            // リストボックスを初期化
            CommandList commandList = GetActiveCommandList();
            commandList.Items.Clear();
            commandList.Enabled = false;
            commandList.FileName = string.Empty;
            commandList.Modified = delegate(string filename) { CheckModified(filename); };
            commandList.SelectedIndexChanged = delegate(int index) { toolStripStatusLabel_RowCount.Text = ((index+1) + " 行目"); };
            // 編集済みフラグを初期化
            modifiedFiles.Clear();
        }
        /// <summary>
        /// 新しくタブページを生成し返す
        /// </summary>
        /// <param name="text">タブに表示するテキスト</param>
        /// <returns>新しいタブページ</returns>
        private TabPage CreateNewTab(string text) {
            TabPage tab = new TabPage();
            tab.Text = text;
            tab.Name = text;
            CommandList commandList = new CommandList();
            commandList.Modified = delegate(string filename) { CheckModified(filename); };
            commandList.Dock = DockStyle.Fill;
            commandList.SelectedIndexChanged = delegate(int index) { toolStripStatusLabel_RowCount.Text = ((index + 1) + " 行目"); };
            tab.Controls.Add(commandList);
            return tab;
        }
        /// <summary>
        /// 変更済みチェックを入れる
        /// </summary>
        /// <param name="filename">チェックを入れるファイル名</param>
        private void CheckModified(string filename) {
            // キー未登録なら定義
            if(!modifiedFiles.ContainsKey(filename)){
                modifiedFiles[filename] = false;
            }
            // 未変更ならチェックをいれる
            if (!modifiedFiles[filename]) {
                modifiedFiles[filename] = true;
                tabControl.TabPages[filename].Text += "*";
            }
        }
        /// <summary>
        /// 変更済みチェックをはずす
        /// </summary>
        /// <param name="filename">チェックをはずすファイル名</param>
        private void UncheckModified(string filename) {
            // キー未登録なら定義
            if (!modifiedFiles.ContainsKey(filename)) {
                modifiedFiles[filename] = false;
            }
            // 変更済みならチェックをはずす
            if (modifiedFiles[filename]) {
                modifiedFiles[filename] = false;
                tabControl.TabPages[filename].Text = tabControl.TabPages[filename].Text.TrimEnd('*');
            }
        }
        /// <summary>
        /// 指定したファイルが変更済みかどうか返す
        /// </summary>
        /// <param name="filename">調べるファイル名</param>
        /// <returns>変更済みならtrue</returns>
        private bool IsModified(string filename) {
            if (!modifiedFiles.ContainsKey(filename)) {
                return false;
            }
            return modifiedFiles[filename];
        }
        /// <summary>
        /// 何かひとつでも変更されたファイルがあるかどうか
        /// </summary>
        /// <returns>変更されたファイルがひとつでもあればtrue</returns>
        private bool IsModifiedAny() {
            if (modified) {
                return true;
            }
            foreach (bool b in modifiedFiles.Values) {
                if (b) {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 表示中のタブにあるリストボックスを取得
        /// </summary>
        /// <returns>表示中のリストボックス</returns>
        private CommandList GetActiveCommandList() {
            if (tabControl.SelectedTab == null) {
                return null;
            } else {
                return tabControl.SelectedTab.Controls[0] as CommandList;
            }
        }
        #endregion


        #region プロジェクトツリービュー　（シナリオ）

        /// <summary>
        /// プロジェクトツリービューの名前が変更されようとしているとき
        /// </summary>
        private void treeView_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e) {
            // シナリオファイルのみ可
            if (e.Node.Name != "シナリオデータ") {
                e.CancelEdit = true;
            }
        }
        /// <summary>
        /// プロジェクトツリービューの名前の変更が終わったとき
        /// </summary>
        private void treeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) {
            // 空白文字はキャンセル
            if (e.Label == null || e.Label.Length == 0) {
                e.CancelEdit = true;
                return;
            }
            // 変更なしならキャンセル
            if (e.Label == e.Node.Text) {
                e.CancelEdit = true;
                return;
            }
            // 無効な文字が含まれていたらキャンセル
            foreach (char c in Path.GetInvalidFileNameChars()) {
                if (e.Label.IndexOf(c) >= 0) {
                    e.CancelEdit = true;
                    return;
                }
            }
            // ノードの種類ごとに分岐
            string label = e.Label;
            switch (e.Node.Name) {
            case "シナリオデータ":
                // 拡張子が無ければ自動で付ける
                if(!Regex.IsMatch(label, string.Format(@"\{0}$", Const.ScenarioExtension), RegexOptions.Compiled)){
                    label += Const.ScenarioExtension;
                }
                // すでに存在する名前は不可
                foreach (string path in Directory.GetFiles("シナリオ/")) {
                    string filename = Path.GetFileName(path);
                    if(filename == label){
                        MessageBox.Show(label + " はすでに存在します。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        e.CancelEdit = true;
                        return;
                    }
                }
                // 名前を変更し終了
                File.Move("シナリオ/"+e.Node.Text, "シナリオ/"+label);
                // 起動プロジェクトなら設定も変えておく
                if (e.Node.Text == projectData.InitialScenario) {
                    projectData.InitialScenario = label;
                }
                // タブのほうも変えておく
                if(tabControl.TabPages.ContainsKey(e.Node.Text)){
                    // テキストを書き換える
                    tabControl.TabPages[e.Node.Text].Text = label;
                    tabControl.TabPages[e.Node.Text].Name = label;
                    // リストボックスにも関連付け
                    CommandList commandList = tabControl.TabPages[label].Controls[0] as CommandList;
                    commandList.FileName = label;
                    // 変更済みフラグのキーを移す
                    if (modifiedFiles.ContainsKey(e.Node.Text)) {
                        modifiedFiles[label] = modifiedFiles[e.Node.Text];
                        modifiedFiles.Remove(e.Node.Text);
                    }
                    if (IsModified(label)) {
                        tabControl.TabPages[label].Text += "*";
                    }
                }
                e.Node.Text = label;
                e.CancelEdit = true;
                break;
            }
            
        }
        /// <summary>
        /// プロジェクトツリービューでクリックされたとき
        /// </summary>
        private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
            switch (e.Button) {
            case MouseButtons.Right:
                // 右クリックでカーソルを移す
                treeView.SelectedNode = e.Node;
                break;
            }
        }
        /// <summary>
        /// プロジェクトツリービューでダブルクリックされたとき
        /// </summary>
        private void treeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
            if(e.Node.Name == "シナリオデータ"){
                OpenScenario(e.Node.Text);
            } else if (e.Node.Name.Contains("画像データ")) {
                OpenImage(e.Node.Parent.Text + "/" + e.Node.Text);
            } else if (e.Node.Name.Contains("サウンドデータ")) {
                OpenSound(e.Node.Parent.Text + "/" + e.Node.Text);
            }
        }
        /// <summary>
        /// プロジェクトツリービューでキーを押したとき
        /// </summary>
        private void treeView_KeyDown(object sender, KeyEventArgs e) {
            if(treeView.SelectedNode == null){
                return;
            }
            switch(e.KeyCode){
            case Keys.Delete:
                // 子ノードが無いノード（シナリオ、画像、サウンドデータノードの末端ノード）のとき
                if (treeView.SelectedNode.Nodes.Count == 0) {
                    if (treeView.SelectedNode.Name == "シナリオデータ") {
                        // 右クリックメニューの処理を流用
                        context_DeleteScenario_Click(sender, e);
                    } else if (treeView.SelectedNode.Name.Contains("画像データ")) {
                        context_DeleteImage_Click(sender, e);
                    } else if (treeView.SelectedNode.Name.Contains("サウンドデータ")) {
                        context_DeleteSound_Click(sender, e);
                    }
                }
                break;
            }
        }
        /// <summary>
        /// シナリオの右クリックメニューが開くとき
        /// </summary>
        private void contextMenu_ScenarioData_Opening(object sender, CancelEventArgs e) {
            ContextMenuStrip menu = sender as ContextMenuStrip;
            ToolStripMenuItem item = menu.Items["Context_SetInitScenario"] as ToolStripMenuItem;
            bool check = (treeView.SelectedNode.Text == projectData.InitialScenario); 
            // 初期データならチェックをつけ、選択不能にする
            item.Checked = check;
            item.Enabled = !check;
        }
        /// <summary>
        /// シナリオの右クリックメニューからシナリオデータを開く
        /// </summary>
        private void contextMenu_OpenScenario_Click(object sender, EventArgs e) {
            OpenScenario(treeView.SelectedNode.Text);
        }
        /// <summary>
        /// シナリオの右クリックメニューから 名前の変更 を選択したとき
        /// </summary>
        private void context_RenameScenario_Click(object sender, EventArgs e) {
            if (treeView.SelectedNode != null) {
                treeView.SelectedNode.BeginEdit();
            }
        }
        /// <summary>
        /// シナリオの右クリックメニューから 初期起動シナリオ を選択したとき
        /// </summary>
        private void context_SetInitScenario_Click(object sender, EventArgs e) {
            // 初期シナリオを変更
            projectData.InitialScenario = treeView.SelectedNode.Text;
            // 編集済みフラグ
            modified = true;
            // 再描画            
            RefreshScenarioNodes();
        }
        /// <summary>
        /// プロジェクトツリービューを初期化
        /// </summary>
        private void InitProjectTree() {
            treeView.Nodes["プロジェクト"].Text = projectData.Name;
            // シナリオ・画像・サウンドノードの子ノードを再構築
            RefreshScenarioNodes();
            RefreshImageNodes();
            RefreshSoundNodes();
            // シナリオノード展開
            treeView.Nodes["プロジェクト"].Expand();
            treeView.Nodes["プロジェクト"].Nodes["シナリオ"].Expand();
        }
        /// <summary>
        /// シナリオノード以下にあるノードを再構築
        /// </summary>
        private void RefreshScenarioNodes() {
            treeView.SuspendLayout();
            treeView.Nodes["プロジェクト"].Nodes["シナリオ"].Nodes.Clear();
            // Scenariosディレクトリにあるシナリオファイルをすべてノードに登録
            foreach (string path in Directory.GetFiles("シナリオ")) {
                string filename = Path.GetFileName(path);
                string ext = Path.GetExtension(path);
                if (ext == Const.ScenarioExtension) {
                    TreeNode node = new TreeNode();
                    node.Text = filename;
                    node.Name = "シナリオデータ";
                    node.ContextMenuStrip = contextMenu_ScenarioData;
                    node.ImageKey = node.SelectedImageKey = "ファイル青.gif";
                    // 初期シナリオなら下線を引く
                    if (filename == projectData.InitialScenario) {
                        node.NodeFont = new Font(treeView.Font.Name, treeView.Font.Size, FontStyle.Underline);
                    }
                    treeView.Nodes["プロジェクト"].Nodes["シナリオ"].Nodes.Add(node);
                }
            }
            treeView.ResumeLayout();
        }
        #endregion


        #region プロジェクトツリービュー　（画像・サウンド）

        /// <summary>
        /// 画像ファイルノードで「開く」を選択したとき
        /// </summary>
        private void context_OpenImage_Click(object sender, EventArgs e) {
            OpenImage(treeView.SelectedNode.Text);
        }
        /// <summary>
        /// 画像を開く
        /// </summary>
        /// <param name="filename">開くファイル名</param>
        private void OpenImage(string filename) {
            string path = ("画像/" + filename).Replace("/", "\\");
            try {
                Process.Start(path);
            } catch (Exception e) {
                MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        /// <summary>
        /// サウンドファイルノードで「再生」を選択したとき
        /// </summary>
        private void context_PlaySound_Click(object sender, EventArgs e) {
            OpenSound(treeView.SelectedNode.Text);
        }
        /// <summary>
        /// サウンドを再生する
        /// </summary>
        /// <param name="filename">再生するファイル名</param>
        private void OpenSound(string filename) {
            string path = ("サウンド/" + filename).Replace("/", "\\");
            try {
                Process.Start(path);
            } catch (Exception e) {
                MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        /// <summary>
        /// 画像ファイルノードで「削除」を選択したとき
        /// </summary>
        private void context_DeleteImage_Click(object sender, EventArgs e) {
            // 確認ダイアログを表示
            string filename = treeView.SelectedNode.Text;
            string path = "画像/" + treeView.SelectedNode.Parent.Text + "/" + filename;
            DialogResult result = MessageBox.Show(filename + " を削除しますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            if (result == DialogResult.Yes) {
                // 削除実行
                File.Delete(path);
                // ツリーノード再構築
                RefreshImageNodes();
            }
        }
        /// <summary>
        /// サウンドファイルノードで「削除」を選択したとき
        /// </summary>
        private void context_DeleteSound_Click(object sender, EventArgs e) {
            // 確認ダイアログを表示
            string filename = treeView.SelectedNode.Text;
            string path = "サウンド/" + treeView.SelectedNode.Parent.Text + "/" + filename;
            DialogResult result = MessageBox.Show(filename + " を削除しますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            if (result == DialogResult.Yes) {
                // 削除実行
                File.Delete(path);
                // ツリーノード再構築
                RefreshSoundNodes();
            }
        }
        /// <summary>
        /// 「インポート」を選択したとき
        /// </summary>
        private void context_Import_Click(object sender, EventArgs e) {
            // 画像・サウンド　どちらのインポートをするか場合分け
            switch (treeView.SelectedNode.Parent.Text) {
            case "画像":
                ImportImage();
                break;
            case "サウンド":
                ImportSound();
                break;
            }
        }
        /// <summary>
        /// 画像のインポート
        /// </summary>
		/// [2008/06/20] Luice 複数ファイル対応
        private void ImportImage() {
            // ファイル選択ダイアログを表示
            OpenFileDialog dialog = new OpenFileDialog();
            // フィルタの作成
            StringBuilder sb = new StringBuilder();
            foreach (string ext in Const.ImageExtensions) {
                sb.Append("*").Append(ext).Append(";");
            }
            dialog.Filter = "画像ファイル (" + sb.ToString() + ")|" + sb.ToString();
            dialog.CheckPathExists = true;
            dialog.CheckFileExists = true;
            dialog.RestoreDirectory = true;
			dialog.Multiselect = true;
			DialogResult result = dialog.ShowDialog();
			if (result == DialogResult.OK)
			{
				foreach (string path in dialog.FileNames)
				{
					// ファイル名を取得
					string filename = Path.GetFileName(path);
					// コピー先ディレクトリ
					string target = "画像/" + treeView.SelectedNode.Text + "/";
					// 既に画像フォルダに同名のファイルが有る場合は確認メッセージを表示
					foreach (string imagepath in Directory.GetFiles(target))
					{
						string imagefile = Path.GetFileName(imagepath);
						if (filename == imagefile)
						{
							result = MessageBox.Show(filename + " は既に存在します。\n既存のファイルと置き換えますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
							if (result == DialogResult.Cancel)
							{
								return;
							}
							break;
						}
					}
					// ファイルをImagesフォルダへコピー
					try
					{
						File.Copy(path, (target + filename), true);
					}
					catch (Exception e)
					{
						MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
				// ツリービューを再描画
				RefreshImageNodes();
				// 画像ノードを開く
				treeView.Nodes["プロジェクト"].Expand();
				treeView.Nodes["プロジェクト"].Nodes["画像"].Expand();
				treeView.Nodes["プロジェクト"].Nodes["画像"].Nodes[treeView.SelectedNode.Name].Expand();
			}
        }
        /// <summary>
        /// 画像ノード以下にあるノードを再構築
        /// </summary>
        private void RefreshImageNodes() {
            treeView.BeginUpdate();
            // 一旦クリア
            foreach (TreeNode node in treeView.Nodes["プロジェクト"].Nodes["画像"].Nodes) {
                node.Nodes.Clear();
            }
            // 画像ディレクトリ以下にある画像ファイルをすべてノードに登録
            foreach (string dir in Directory.GetDirectories("画像")) {
                // 画像ディレクトリ可の全てのディレクトリにループ
                string dirname = Path.GetFileName(dir);
                foreach (string file in Directory.GetFiles(dir)) {
                    string filename = Path.GetFileName(file);
                    string ext = Path.GetExtension(file).ToLower();
                    foreach (string _ext in Const.ImageExtensions) {
                        if (ext == _ext) {
                            TreeNode node = new TreeNode();
                            node.Text = filename;
                            node.Name = "画像データ/" + dirname;
                            node.ContextMenuStrip = contextMenu_ImageData;
                            node.ImageKey = node.SelectedImageKey = "汎用ファイル.gif";
                            treeView.Nodes["プロジェクト"].Nodes["画像"].Nodes[dirname].Nodes.Add(node);
                            break;
                        }
                    }
                }
            }
            treeView.EndUpdate();
        }
        /// <summary>
        /// サウンドのインポート
        /// </summary>
		/// [2008/06/20] Luice 複数ファイル対応
		private void ImportSound()
		{
            // ファイル選択ダイアログを表示
            OpenFileDialog dialog = new OpenFileDialog();
            // フィルタの作成
            StringBuilder sb = new StringBuilder();
            foreach (string ext in Const.SoundExtensions) {
                sb.Append("*").Append(ext).Append(";");
            }
            dialog.Filter = "オーディオファイル (" + sb.ToString() + ")|" + sb.ToString();
            dialog.CheckPathExists = true;
            dialog.CheckFileExists = true;
            dialog.RestoreDirectory = true;
			dialog.Multiselect = true;
			DialogResult result = dialog.ShowDialog();
            if (result == DialogResult.OK) {
				foreach (string path in dialog.FileNames)
				{
					// ファイル名を取得
					string filename = Path.GetFileName(path);
					// コピー先ディレクトリ
					string target = "サウンド/" + treeView.SelectedNode.Text + "/";
					// 既にサウンドフォルダに同名のファイルが有る場合は確認メッセージを表示
					foreach (string soundpath in Directory.GetFiles(target))
					{
						string soundfile = Path.GetFileName(soundpath);
						if (filename == soundfile)
						{
							result = MessageBox.Show(filename + " は既に存在します。\n既存のファイルと置き換えますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
							if (result == DialogResult.Cancel)
							{
								return;
							}
							break;
						}
					}
					// ファイルをSoundsフォルダへコピー
					try
					{
						File.Copy(path, (target + filename), true);
					}
					catch (Exception e)
					{
						MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
                // ツリービューを再描画
                RefreshSoundNodes();
                // サウンドノードを開く
                treeView.Nodes["プロジェクト"].Expand();
                treeView.Nodes["プロジェクト"].Nodes["サウンド"].Expand();
                treeView.Nodes["プロジェクト"].Nodes["サウンド"].Nodes[treeView.SelectedNode.Name].Expand();
            }
        }
        /// <summary>
        /// サウンドノード以下にあるノードを再構築
        /// </summary>
        private void RefreshSoundNodes() {
            treeView.BeginUpdate();
            // 一旦クリア
            foreach (TreeNode node in treeView.Nodes["プロジェクト"].Nodes["サウンド"].Nodes) {
                node.Nodes.Clear();
            }
            // サウンドディレクトリ以下にあるサウンドファイルをすべてノードに登録
            foreach (string dir in Directory.GetDirectories("サウンド")) {
                // サウンドディレクトリ可の全てのディレクトリにループ
                string dirname = Path.GetFileName(dir);
                foreach (string file in Directory.GetFiles(dir)) {
                    string filename = Path.GetFileName(file);
                    string ext = Path.GetExtension(file).ToLower();
                    foreach (string _ext in Const.SoundExtensions) {
                        if (ext == _ext) {
                            TreeNode node = new TreeNode();
                            node.Text = filename;
                            node.Name = "サウンドデータ/" + dirname;
                            node.ContextMenuStrip = contextMenu_SoundData;
                            node.ImageKey = node.SelectedImageKey = "音楽ファイル.gif";
                            treeView.Nodes["プロジェクト"].Nodes["サウンド"].Nodes[dirname].Nodes.Add(node);
                            break;
                        }
                    }
                }
            }
            treeView.EndUpdate();
        }
        #endregion


        #region コマンド一覧
        /// <summary>
        /// コマンド一覧の要素をダブルクリックしたとき
        /// </summary>
        private void listView_MouseDoubleClick(object sender, MouseEventArgs e) {
            // プロジェクトを閉じているときは実行しない
            if (projectData == null) {
                return;
            }
            // リストボックスが無いときは実行しない
            if (activeCommandList == null) {
                return;
            }
            // 挿入できない行なら実行しない
            CommandListData? command = activeCommandList.SelectedItem;
            // 選択している行が、文章の表示などの2行目以降の場合は、メニューは無効
            if (command.HasValue && !command.Value.IsSelectable && command.Value.Name != CommandName.無し) {
                return;
            }
            ListViewItem item = listView.GetItemAt(e.X, e.Y);
            if (item != null) {
                // 選択したコマンド名を取得し、そのコマンドの挿入ダイアログを表示する
                foreach (CommandName name in Enum.GetValues(typeof(CommandName))) {
                    if (item.Text == name.ToString()) {
                        activeCommandList.ShowCommandDialog(name);
                        return;
                    }
                }
            }
        }
        #endregion


        #region プロジェクト関係

        /// <summary>
        /// 新しいプロジェクト
        /// </summary>
        private void menuItem_NewProject_Click(object sender, EventArgs e) {
            // 未保存なら確認メッセージを出し、キャンセルが押されたら続行しない
            if (!ConfirmSave()) {
                return;
            }
            // 新規作成ダイアログ
            SystemDialog.NewProjectDialog dialog = new SystemDialog.NewProjectDialog();
            DialogResult result = dialog.ShowDialog();
            // 作成ボタンが押されなければ除外
            if (result != DialogResult.OK) {
                return;
            }
            // プロジェクトを作成するパスと、このアプリケーションがあるパス
            string projectPath = dialog.ProjectPath + "/" + dialog.ProjectName + "/";
            string appPath = AppDomain.CurrentDomain.BaseDirectory;
            // 既に存在する場合は確認メッセージ
            if (Directory.Exists(projectPath)) {
                result = MessageBox.Show(projectPath + " は既に存在します。\n上書きしても宜しいですか？", Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                if (result == DialogResult.Cancel) {
                    return;
                }
            }
            // プロジェクトフォルダを作成
            Directory.CreateDirectory(projectPath);
            // 基準フォルダパスを以後のカレントディレクトリに設定
            Environment.CurrentDirectory = projectPath;
            // 各データ格納フォルダを作成
            Directory.CreateDirectory("シナリオ");
            Directory.CreateDirectory("画像");
            Directory.CreateDirectory("画像/立ち絵");
            Directory.CreateDirectory("画像/背景");
			Directory.CreateDirectory("画像/ボタン");
			Directory.CreateDirectory("サウンド");
            Directory.CreateDirectory("サウンド/BGM");
            Directory.CreateDirectory("サウンド/SE");
			// プロジェクトデータを作成
            string initialScenario = "data" + Const.ScenarioExtension;
            projectData = new ProjectData(dialog.ProjectName, initialScenario, dialog.GameTitle);
            // XMLファイルに書き込む
            projectData.Save();
            // 初期シナリオファイルを作成
            CreateScenarioFile(initialScenario);
            // ADV Evaluatorへのショートカットを作成
            Shortcut.Create(
                projectData.Name,
                appPath + "ADV Evaluator.exe",
                projectPath + projectData.FileName
            );
            // ツリービューなどの操作を可能にする
            ControlsEnable(true);
            // タイトル変更
            this.Text = projectData.Name + " - " + Application.ProductName;
            // 変更済みフラグを初期化
            modifiedFiles.Clear();
            modified = false;
            // タブ、コマンドリストを初期化する
            ClearAllTabs();
            // シナリオデータをリストボックスに表示
            InitProjectTree();
            // 初期シナリオを開いてしまう
            OpenScenario(initialScenario);
            // 立ち絵表示に最大レイヤー数を設定(Default:1)
            ADV_Editor.CommandDialog.ImageDialog.LayerSlot = 1;
        }
        /// <summary>
        /// プロジェクトを開く
        /// </summary>
        private void menuItem_OpenProject_Click(object sender, EventArgs e) {
            // 未保存なら確認メッセージを出し、キャンセルが押されたら続行しない
            if (!ConfirmSave()) {
                return;
            }
            // 開くダイアログ
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = string.Format("ADV Editor プロジェクト(*{0})|*{0}", Const.ProjectExtension);
            dialog.InitialDirectory = Environment.CurrentDirectory;
            dialog.CheckFileExists = true;
            dialog.CheckPathExists = true;
            dialog.RestoreDirectory = true;
            DialogResult result = dialog.ShowDialog();
            if (result == DialogResult.OK) {
                OpenProject(dialog.FileName);
            }
        }
        /// <summary>
        /// プロジェクトを開く
        /// </summary>
        /// <param name="filename"></param>
        private void OpenProject(string filename) {
            Environment.CurrentDirectory = Path.GetDirectoryName(filename) + "/";
            projectData = ProjectData.Load(filename);
            // タイトル変更
            this.Text = projectData.Name + " - " + Application.ProductName;
            // ツリービューなどの操作を可能にする
            ControlsEnable(true);
            // コマンドリストを初期化
            CommandList commandList = GetActiveCommandList();
            commandList.Items.Clear();
            CommandList.Clipboard.Clear();
            // 変更済みフラグを初期化
            modifiedFiles.Clear();
            modified = false;
            // タブを初期化
            ClearAllTabs();
            // プロジェクトツリーを表示
            InitProjectTree();
            // 立ち絵表示に最大レイヤー数を設定
            ADV_Editor.CommandDialog.ImageDialog.LayerSlot = projectData.LayerSlot;
        }
        /// <summary>
        /// 上書き保存する
        /// </summary>
        private void menuItem_SaveProject_Click(object sender, EventArgs e) {
            SaveProject();
        }
        /// <summary>
        /// プロジェクトを閉じる
        /// </summary>
        private void menuItem_CloseProject_Click(object sender, EventArgs e) {
            // 未保存なら確認メッセージを出し、キャンセルが押されたら続行しない
            if (!ConfirmSave()) {
                return;
            }
            projectData = null;
            // ノードを元に戻して展開されていたのを閉じる
            treeView.Nodes["プロジェクト"].Text = "プロジェクト";
            treeView.Enabled = false;
            treeView.CollapseAll();
            ClearAllTabs();
            // メニュー項目を選択不可にする
            ControlsEnable(false);
            this.Text = Application.ProductName;
            toolStripStatusLabel_RowCount.Text = "";
            modifiedFiles.Clear();
            modified = false;
        }
        /// <summary>
        /// プロジェクトが開かれないと操作できないコントロールのEnabledを制御する
        /// </summary>
        /// <param name="b">Enabledの値</param>
        private void ControlsEnable(bool b) {
            treeView.Enabled = b;
            tabControl.Enabled = b;
            menuItem_SaveProject.Enabled = b;
            menuItem_CloseProject.Enabled = b;
			menuItem_Publish.Enabled = b;
			menuItem_ProjectSetting.Enabled = b;
            menuItem_TestPlay.Enabled = b;
            menuItem_Copy.Enabled = b;
            menuItem_Cut.Enabled = b;
            menuItem_Delete.Enabled = b;
            menuItem_Paste.Enabled = b;
            toolStripButton_NewScenario.Enabled = b;
            toolStripButton_SaveProject.Enabled = b;
            toolStripButton_TestPlay.Enabled = b;
            toolStripButton_Copy.Enabled = b;
            toolStripButton_Cut.Enabled = b;
            toolStripButton_Delete.Enabled = b;
            toolStripButton_Paste.Enabled = b;
        }
        /// <summary>
        /// 変更を保存せずに終了、新規作成等をしようとした時に表示する、"はい""いいえ""キャンセル"三択の確認メッセージ。
        /// "はい" を選んだ場合、プロジェクトを保存する。
        /// </summary>
        /// <returns>"はい"若しくは"いいえ"ならtrue、"キャンセル"ならfalse。メッセージが出なかった場合もtrue</returns>
        private bool ConfirmSave() {
            // プロジェクトを開いていて、何か変更があるとき
            if (projectData != null && IsModifiedAny()) {
                // 確認メッセージ
                switch (MessageBox.Show("変更を保存しますか？", Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1)) {
                case DialogResult.Yes:
                    // 保存
                    SaveProject();
                    return true;
                case DialogResult.No:
                    // 何もしない
                    return true;
                case DialogResult.Cancel:
                    // この先の処理を続けない
                    return false;
                default:
                    throw null;  // こないとおもう
                }
            } else {
                return true;
            }
        }
        #endregion


        #region シナリオファイルへの操作

        /// <summary>
        /// プロジェクトツリーノードのシナリオデータノード上での右クリックで「削除」を選んだとき
        /// </summary>
        private void context_DeleteScenario_Click(object sender, EventArgs e) {
            string filename = treeView.SelectedNode.Text;
            // 初期シナリオは削除できない
            if (filename == projectData.InitialScenario) {
                MessageBox.Show(filename + " は初期起動シナリオなので、削除できません。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            // 確認メッセージ
            DialogResult result = MessageBox.Show(filename + " を削除しますか？", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            if (result == DialogResult.Yes) {
                switch (treeView.SelectedNode.Name) {
                case "シナリオデータ":
                    File.Delete("シナリオ/" + filename);
                    RefreshScenarioNodes();
                    int tabIndex = tabControl.TabPages.IndexOfKey(filename);
                    // タブで開いていれば閉じる
                    if (tabIndex != -1) {
                        // タブが１つで、そのタブを消そうとしているとき
                        if (tabControl.TabCount == 1 && tabIndex == 0) {
                            // 消さずにそのタブのコマンドリストを空にする
                            ClearAllTabs();
                        } else {
                            // 編集済みチェックをはずす
                            UncheckModified(tabControl.TabPages[tabIndex].Name);
                            // タブを消す
                            tabControl.TabPages.RemoveAt(tabIndex);
                        }
                    }
                    break;
                case "画像データ":
                    File.Delete("画像/" + filename);
                    RefreshImageNodes();
                    break;
                case "BGMデータ":
                    File.Delete("サウンド/BGM/" + filename);
                    RefreshSoundNodes();
                    break;
                case "SEデータ":
                    File.Delete("サウンド/SE/" + filename);
                    RefreshSoundNodes();
                    break;
				case "定義ファイル":
					File.Delete("データ/定義ファイル/" + filename);
					RefreshSoundNodes();
					break;
                }

            }
        }
        /// <summary>
        /// 新しいシナリオデータを作成する。シナリオフォルダ内に作成される。
        /// </summary>
        /// <param name="filename">ファイル名</param>
        private void CreateScenarioFile(string filename) {
            // 初期データをバイナリで書き込む
            using (FileStream fs = new FileStream("シナリオ/" + filename, FileMode.Create, FileAccess.Write)) {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, new CommandData[0]);  // 空の配列を入れておく
            }
        }
        /// <summary>
        /// 指定されたシナリオファイルを削除
        /// </summary>
        /// <param name="filename">削除するシナリオファイル名</param>
        private void DeleteScenario(string filename) {

        }
        /// <summary>
        /// シナリオデータを開き、タブ・コマンドリストに反映する
        /// </summary>
        /// <param name="filename">開くシナリオファイル名</param>
        private void OpenScenario(string filename) {
            // タブが１つで空白ならそこに反映
            if (tabControl.TabCount == 1 && tabControl.SelectedTab.Text == "about:blank") {
                tabControl.SelectedTab.Text = filename;
                tabControl.SelectedTab.Name = filename;
                // タブが２つ以上のとき
            } else {
                // すでに同名のファイルを開いたタブがあればそれを選択する
                if (tabControl.TabPages.ContainsKey(filename)) {
                    tabControl.SelectedTab = tabControl.TabPages[filename];
                    return;
                // 見つからなければ新しくタブを作り、そこに反映する
                } else {
                    TabPage newTab = CreateNewTab(filename);
                    tabControl.TabPages.Insert(tabControl.SelectedIndex + 1, newTab);
                    tabControl.SelectedTab = newTab;
                    tabControl.SelectedTab.ImageKey = "ファイル青.gif";
                }
            }
            activeCommandList = GetActiveCommandList();
            // 選択中のコマンドリストに反映
            InitCommandList(filename);
        }

		/// <summary>
		/// 新しい定義ファイルを作成する。定義ファイルフォルダ内に作成される。
		/// </summary>
		/// <param name="filename">ファイル名</param>
		private void CreateDefFile(string filename)
		{
			// 初期データをバイナリで書き込む
			using (FileStream fs = new FileStream("データ/定義ファイル/" + filename, FileMode.Create, FileAccess.Write))
			{}
		}

        #endregion


        #region ツールバー
        /// <summary>
        /// シナリオファイルを追加
        /// </summary>
        private void toolStripButton_NewScenario_Click(object sender, EventArgs e) {
            SystemDialog.NewScenarioDialog dialog = new SystemDialog.NewScenarioDialog();
            if (dialog.ShowDialog() == DialogResult.OK) {
                // 新規作成
                CreateScenarioFile(dialog.FileName);
                // ツリービューを再構築
                RefreshScenarioNodes();
                // 変更済みフラグON
                modified = true;
            }
        }
        /// <summary>
        /// 切り取り
        /// </summary>
        private void toolStripButton_Cut_Click(object sender, EventArgs e) {
            if (activeCommandList != null) {
                activeCommandList.CopyCommand();
                activeCommandList.DeleteCommand();
            }
        }
        /// <summary>
        /// コピー
        /// </summary>
        private void toolStripButton_Copy_Click(object sender, EventArgs e) {
            if (activeCommandList != null) {
                activeCommandList.CopyCommand();
            }
        }
        /// <summary>
        /// 貼り付け
        /// </summary>
        private void toolStripButton_Paste_Click(object sender, EventArgs e) {
            if (activeCommandList != null) {
                activeCommandList.PasteCommand();
            }
        }
        /// <summary>
        /// 削除
        /// </summary>
        private void toolStripButton_Delete_Click(object sender, EventArgs e) {
            if (activeCommandList != null) {
                activeCommandList.DeleteCommand();
            }
        }
        #endregion


        #region メインメニュー

        /// <summary>
        /// ファイル　メニューが表示されるとき
        /// </summary>
        private void menuItem_File_DropDownOpening(object sender, EventArgs e) {
            this.menuItem_SaveProject.Enabled = IsModifiedAny();
            this.menuItem_CloseProject.Enabled = (projectData != null);
        }
        /// <summary>
        /// コマンド一覧
        /// </summary>
        private void menuItem_CommandDialog_Click(object sender, EventArgs e) {
            //ShowCommandDialog();
        }
        /// <summary>
        /// ゲーム設定
        /// </summary>
        private void menuItem_ProjectSetting_Click(object sender, EventArgs e) {
            SystemDialog.ProjectSettingDialog dialog = new SystemDialog.ProjectSettingDialog(projectData);
            if (dialog.ShowDialog() == DialogResult.OK) {
                projectData = dialog.ProjectData;
                modified = true;
                // 立ち絵表示に最大レイヤー数を設定
                ADV_Editor.CommandDialog.ImageDialog.LayerSlot = projectData.LayerSlot;
            }
        }
        /// <summary>
        /// テストプレイ
        /// </summary>
        private void menuItem_Testplay_Click(object sender, EventArgs e) {
            // 未保存なら確認メッセージを出し、キャンセルが押されたら続行しない
            if (!ConfirmSave()) {
                return;
            }
            // 起動中はエディタを操作不能にする
            this.Enabled = false;
            SystemDialog.ExecutingDialog executing = new SystemDialog.ExecutingDialog(this);
            executing.Show();
            // 評価機起動
            ADV_Evaluator.Program.Main();
            // 操作不能状態を解く
            executing.Close();
            this.Enabled = true;
            this.Activate();
        }
        /// <summary>
        /// バージョン情報
        /// </summary>
        private void menuItem_VersionInfo_Click(object sender, EventArgs e) {
            MessageBox.Show(
                Application.ProductName + "  Version " + Application.ProductVersion,
                Application.ProductName,
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
        }
        #endregion


        #region 読み込み

        /// <summary>
        /// シナリオデータを読み込み、コマンドをツリービューに表示する
        /// </summary>
        /// <param name="filename">"シナリオ"フォルダにあるシナリオデータ</param>
        private void InitCommandList(string filename) {
            activeCommandList.Enabled = true;
            activeCommandList.FileName = filename;
            // 描画開始
            activeCommandList.BeginUpdate();
            activeCommandList.Items.Clear();
            // データを読み込んで配列に格納
            FileStream fs = null;
#if DEBUG
            try {
#endif
                fs = new FileStream("シナリオ/" + filename, FileMode.Open, FileAccess.Read);
                // 読み込んで逆シリアル化する
                BinaryFormatter bf = new BinaryFormatter();
                CommandData[] commands = bf.Deserialize(fs) as CommandData[];
                // リストボックスに要素をセット
                activeCommandList.BeginUpdate();
                for (int i = 0; i < commands.Length; i++) {
                    CommandListData c = new CommandListData(commands[i]);
                    activeCommandList.Items.Add(c);
                    // 表示する値が複数行の場合、2行目以降もそれぞれListBoxへ挿入する
                    if (c.IsMultiline) {
                        for (int j = 0; j < c.RestLines.Length; j++) {
                            CommandListData child = new CommandListData(c.Name, c.RestLines[j]);
                            activeCommandList.Items.Add(child);
                        }
                    }
                }
                // 最後の要素としてひとつ余分にリストをつける
                activeCommandList.Items.Add(new CommandListData(CommandName.無し, new NullParams()));
                // インデント調整
                activeCommandList.UpdateIndent();
                activeCommandList.SelectedIndex = 0;
                activeCommandList.EndUpdate();
#if DEBUG
            } catch (Exception e) {
                MessageBox.Show("シナリオデータの読み込みに失敗しました。\n\n" + e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(1);
            } finally {
#endif
                if (fs != null) fs.Close();
#if DEBUG
            }
#endif
            // 描画終了
            activeCommandList.EndUpdate();
        }
        #endregion


        #region 保存

        /// <summary>
        /// シナリオファイルをシナリオディレクトリ下に保存する
        /// </summary>
        /// <param name="filename">保存するファイル名</param>
        private void SaveScenarioFile(string filename) {
            // タブが１つで about:blank なら処理しない
            if(tabControl.TabPages[0].Text == "about:blank"){
                return;
            }
            // コマンドが描かれたリストボックスを取得
            CommandList commandList = tabControl.TabPages[filename].Controls[0] as CommandList;
            // Data_CommandListからData_Commandの配列を作る
            List<CommandData> list = new List<CommandData>();
            for (int i = 0; i < commandList.Items.Count-1; i++) {
                CommandListData cmd = commandList[i];
                // 複数行コマンドの2行目以降のコマンドでなければ保存する
                if (!cmd.IsRestLine) {
                    list.Add(cmd.Data);
                }
            }
            // コマンドリストをバイナリでファイルに書き込む
            using (FileStream fs = new FileStream("シナリオ/" + filename, FileMode.Create, FileAccess.Write)) {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, list.ToArray());
            }
            // 編集済みチェックをはずす
            UncheckModified(filename);
        }
        /// <summary>
        /// プロジェクトを保存する
        /// </summary>
        private void SaveProject() {
            // 何も変更が無ければ何もしない
            if (!IsModifiedAny()) {
                return;
            }
            // 現在開いている全てのタブに対して
            foreach (TabPage page in tabControl.TabPages) {
                // タブの名前（ファイル名）のファイルを保存
                SaveScenarioFile(page.Name);
                // 編集済みチェックをはずす
                UncheckModified(page.Name);
            }
            modified = false;
            // プロジェクトファイルの保存
            projectData.Save();
        }
        #endregion



        #region その他

        /// <summary>
        /// プログラムを終了する前に発生する。Application.Exitで終了した場合は呼ばれない。
        /// </summary>
        private void Form_Main_FormClosing(object sender, FormClosingEventArgs e) {
            // プロジェクトを開いていないときは止めない
            if(projectData == null){
                return;
            // 何も変更が無ければ止めない
            } else if (!IsModifiedAny()) {
                return;
            }
            // 未保存なら確認メッセージを出す
            ConfirmSave();
        }

        /// <summary>
        /// 終了
        /// </summary>
        private void menuItem_Exit_Click(object sender, EventArgs e) {
            this.Close();
        }
        #endregion

		/// <summary>
		/// 発行
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void menuItem_Publish_Click(object sender, EventArgs e)
		{
			try
			{
				string appPath = AppDomain.CurrentDomain.BaseDirectory;

				if (!Directory.Exists("Publish"))
				{
					Directory.CreateDirectory("Publish");
				}
				// プロジェクトフォルダを作成
				string pub_name = "Publish/" + projectData.Name;
				if (Directory.Exists(pub_name))
				{
					Directory.Delete(pub_name, true);
				}
				Directory.CreateDirectory(pub_name);
				// 各データ格納フォルダを作成
				Directory.CreateDirectory(pub_name + "/シナリオ");
				Directory.CreateDirectory(pub_name + "/画像");
				Directory.CreateDirectory(pub_name + "/画像/立ち絵");
				Directory.CreateDirectory(pub_name + "/画像/背景");
				Directory.CreateDirectory(pub_name + "/画像/ボタン");
				Directory.CreateDirectory(pub_name + "/サウンド");
				Directory.CreateDirectory(pub_name + "/サウンド/BGM");
				Directory.CreateDirectory(pub_name + "/サウンド/SE");
				Directory.CreateDirectory(pub_name + "/lib");
				Directory.CreateDirectory(pub_name + "/lib/x64");
				Directory.CreateDirectory(pub_name + "/lib/x86");

				string copy_dir = pub_name + "/";
				foreach (string file in Directory.GetFiles("./", "*" + Const.ProjectExtension))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}
				File.Copy(appPath + "ADV Evaluator.exe", copy_dir + projectData.Name + ".exe", true);
				File.Copy(appPath + "AxInterop.WMPLib.dll", copy_dir + "AxInterop.WMPLib.dll", true);
				File.Copy(appPath + "Interop.WMPLib.dll", copy_dir + "Interop.WMPLib.dll", true);
				File.Copy(appPath + "Yanesdk.dll", copy_dir + "Yanesdk.dll", true);
				File.Copy(appPath + "Yanesdk.dll.config", copy_dir + "Yanesdk.dll.config", true);
				copy_dir = pub_name + "/lib/x64/";
				foreach (string file in Directory.GetFiles(appPath + "lib/x64"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}
				copy_dir = pub_name + "/lib/x86/";
				foreach (string file in Directory.GetFiles(appPath + "lib/x86"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}

				copy_dir = pub_name + "/シナリオ/";
				foreach (string file in Directory.GetFiles("シナリオ"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}

				copy_dir = pub_name + "/画像/立ち絵/";
				foreach (string file in Directory.GetFiles("画像/立ち絵"))
				{
					//File.Copy(file, copy_dir + Path.GetFileName(file), true);
					File.Copy(file, copy_dir + Path.GetFileNameWithoutExtension(file) + "." + Const.ImageEx, true);
				}

				copy_dir = pub_name + "/画像/背景/";
				foreach (string file in Directory.GetFiles("画像/背景"))
				{
					//File.Copy(file, copy_dir + Path.GetFileName(file), true);
					File.Copy(file, copy_dir + Path.GetFileNameWithoutExtension(file) + "." + Const.ImageEx, true);
				}

				copy_dir = pub_name + "/画像/ボタン/";
				foreach (string file in Directory.GetFiles("画像/ボタン"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}

				copy_dir = pub_name + "/サウンド/BGM/";
				foreach (string file in Directory.GetFiles("サウンド/BGM"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}

				copy_dir = pub_name + "/サウンド/SE/";
				foreach (string file in Directory.GetFiles("サウンド/SE"))
				{
					File.Copy(file, copy_dir + Path.GetFileName(file), true);
				}

				MessageBox.Show("発行致しました。");
			}
			catch (Exception ex)
			{
				MessageBox.Show("発行に失敗致しました。" + Environment.NewLine + ex.Message);
			}
		}

    }

}